#include "minesweeper.h"

Minesweeper::Minesweeper()
{
	Pos = Vector2D(RandFloat()*400,RandFloat()*300);

	Brain = new NeuralNet();

	Rotation = RandFloat()*6.18;
	lTrack = 0.16;
	rTrack = lTrack;
	Fitness = 0;
	ClosestMine=0;
}

/*-------------------------------------------------------------------------------------------------------------*/
Minesweeper::~Minesweeper()
{
	delete Brain;
}

/*-------------------------------------------------------------------------------------------------------------*/
bool Minesweeper::Initialize()
{
	if (!this->LoadIni("data/graphics/sweeper.spr"))
	{
		return false;
	}
	return true;
}

/*-------------------------------------------------------------------------------------------------------------*/
void Minesweeper::Move(double x, double y)
{
	Pos.x+=x;
	Pos.y+=y;

	x= Pos.x;
	y= Pos.y;
}

/*-------------------------------------------------------------------------------------------------------------*/
void Minesweeper::Update(float dt, std::vector<Mine*> &mines)
{
	//this will store all the inputs for the NN
	vector<double> inputs;	

	//get vector to closest mine
	Vector2D vClosestMine = GetClosestMine(mines);

	//normalise it
	Vec2DNormalize(vClosestMine);

	//add in vector to closest mine
	inputs.push_back(vClosestMine.x);
	inputs.push_back(vClosestMine.y);

	//add in sweepers look at vector
	inputs.push_back(LookAt.x);
	inputs.push_back(LookAt.y);


	//update the brain and get feedback
	vector<double> output = Brain->Update(inputs);

	//assign the outputs to the sweepers left & right tracks
	lTrack = output[0];
	rTrack = output[1];

	//calculate steering forces
	double RotForce = lTrack - rTrack;

	//clamp rotation
	Clamp(RotForce, -0.3, 0.3);

	Rotation += RotForce;

	Speed = (lTrack + rTrack);	

	//update Look At 
	LookAt.x = -sin(Rotation);
	LookAt.y = cos(Rotation);
	
	//update position
	
	Pos += (LookAt * Speed);

	//wrap around window limits
	if (Pos.x > 400.0) Pos.x = 388.0;
	if (Pos.x < -400.0) Pos.x = -388.0;
	if (Pos.y > 300.0) Pos.y = 288.0;
	if (Pos.y < -300) Pos.y = -288.0;

	SetPos(Pos.x, Pos.y);

	Sprite::Update(dt);
	
}

/*-------------------------------------------------------------------------------------------------------------*/
Vector2D Minesweeper::GetClosestMine(vector<Mine*> &mines)
{
	double closestSoFar = 99999;
	Vector2D closestObject(0,0);

	for (int i=0; i<mines.size(); i++)
	{
		Vector2D auxVec(mines[i]->GetPosX(), mines[i]->GetPosY());

		double lenToObject = Vec2DLength(auxVec - Pos);

		if (lenToObject < closestSoFar)
		{
			closestSoFar	= lenToObject;

			closestObject	= Pos - auxVec;

			ClosestMine = i;
		}
	}

	return closestObject;

}

/*-------------------------------------------------------------------------------------------------------------*/
int Minesweeper::CheckForMine(vector<Vector2D> &mines, double size)
{
	Vector2D DistToObject = Pos - mines[ClosestMine];

	if (Vec2DLength(DistToObject) < (size + 5))
	{
		return ClosestMine;
	}

	return -1;
}

/*-------------------------------------------------------------------------------------------------------------*/

void Minesweeper::Reset()
{
	Fitness = 0;
	Rotation = RandFloat()*6.28;
	Pos = Vector2D(RandFloat()*400,RandFloat()*300);
}

/*-------------------------------------------------------------------------------------------------------------*/
void Minesweeper::Draw()
{
	Sprite::Draw();
}


